/**
 * @file genpid.h
 * @author hpy (yuan_hp@qq.com)
 * @brief  GenPID控制(PID),基于整数
 * @version 0.1
 * @date 2023-07-27
 * 
 * @copyright Copyright (c) 2023
 * 
 */

#ifndef __GENPID__H_
#define __GENPID__H_

/**
 * @brief 使能日志打印
 * 
 */
#define GENPID_LOG_ENABLE  0

/**
 * @brief 使能移位计算，避免出现乘除法计算
 * 
 */
#define GENPID_SHIFT_ENABLE 0
/**
 * @brief 驱动函数注册，函数原型 int func(int v)
 * 
 */
typedef int (*OutputDriverFunction_t)(int) ;   // 

/**
 * @brief 控制器对象
 * 
 */
typedef struct genpid_struct      genpid_t ;


#if (GENPID_LOG_ENABLE==1)
#include <stdio.h>
#endif 

#if (GENPID_LOG_ENABLE==1)
#define GENPID_INFO(...) do {\
	printf("%s:%d:%s ",__FILE__,__LINE__,__func__) ;\
	printf(__VA_ARGS__) ;\
	printf("\r\n") ;\
} while(0)
#else
#define GENPID_INFO(...) do {\
    if(0) ; \
} while(0)
#endif

#if (GENPID_LOG_ENABLE==1)
#define GENPID_ASSERT(...) do {\
	printf("%s:%d:%s ",__FILE__,__LINE__,__func__) ;\
	printf(__VA_ARGS__) ;\
	printf("\r\n") ;\
    while (1) ;\
} while(0)
#else
#define GENPID_ASSERT(...) do {\
    if(0) ; \
} while(0)
#endif


#ifdef __cplusplus
extern "C" {
#endif 

/**
 * @brief 注册温控输出函数
 * 
 * @param outFunc 注册的函数实现
 * @return int 
 * 0 ： 操作成功 \n
 * 
 * @code
 * genpid_t g ;
 * int TEC_Driver(int val){ 
 *	int toReg = -val ; 
 *	if(toReg==0) { 
 *		LL_TIM_OC_SetCompareCH2(TIM1, 0); 
 *		LL_TIM_OC_SetCompareCH3(TIM1, 0); 
 *	} 
 *	else if(toReg>0) { 
 *		LL_TIM_OC_SetCompareCH2(TIM1, toReg); 
 *		LL_TIM_OC_SetCompareCH3(TIM1, 0); 
 *	} else { 
 *		LL_TIM_OC_SetCompareCH2(TIM1, 0); 
 *		LL_TIM_OC_SetCompareCH3(TIM1, -toReg); 
 *	} 
 *	return 0; 
 *} 
 * 
 * GenPID_InsatllOutDriver(&g ,TEC_Driver) ; //注册TEC驱动函数 
 * 
 * @endcode 
 */
int GenPID_InstallOutDriver(genpid_t *g ,OutputDriverFunction_t outFunc) ;


/**
 * @brief 初始化GenPID
 *
 * @param g  pid控制对象 
 * @param Kp 设置参数P
 * @param Ki 设置参数I
 * @param Kd 设置参数D
 * @param expect 增量式PID调节的目标值
 * @return int 
 * 0 : 操作成功
 */
int GenPID_Init(genpid_t *g  , int Kp , int Ki ,int Kd , int expect)  ; 

/**
 * @brief 设置PID的缩放因子
 *
 * @param g  pid控制对象 
 * @param val 设置值
 * @return int 
 * 0： 操作成功
 */
int GenPID_SetScaleFactor(genpid_t *g  ,int val) ; 


/**
 * @brief 设置输出的最大值和最小值
 *
 * @param g  pid控制对象 
 * @param min 输出最小值
 * @param max 输出最大值
 * @return int
 * 0 ： 操作成功 
 */
int GenPID_SetOutMaxMin(genpid_t *g  ,int min , int max) ;

/**
 * @brief 进行一次增量式PID运算
 *
 * @param g  pid控制对象 
 * @param feedBackVal 采集得到的反馈值
 * @return int 计算得出的增量
 */
int GenPID_PidCal(genpid_t *g  , int feedBackVal );


/**
 * @brief PID计算和输出以及后续处理都在这里实现
 * 
 * @param g  pid控制对象
 * @param feedBackVal 
 * @param sign 反馈的方向 当<0时计算时增量取反  
 * @return int 
 */
int GenPID_Update(genpid_t *g  ,int feedBackVal,int sign)  ; 

/**
 * @brief 获取输出值
 * @param g  pid控制对象
 * @return int 返回的输出值
 */
int GenPID_GetOutput(genpid_t *g) ; 

/**
 * @brief 获取PID目标值
 *
 * @param g  pid控制对象 
 * @return int PID目标值
 */
int GenPID_GetExpect(genpid_t *g ) ;

/**
 * @brief 设置PID目标值
 *
 * @param exp 目标值
 * @return int
 * 0:操作成功
 */
int GenPID_SetExpect(genpid_t *g  ,int exp) ;


/**
 * @brief PID控制结构体
 * 
 */
struct genpid_struct {
    int expect ; 
    int Kp , Ki , Kd ; 
    int scale ; //缩放因子

    int e0 , e1 ,e2 ; 
    int output ; //输出值
    int current ; 

    int outputMaxVal  ; 
    int outputMinVal  ; 

    OutputDriverFunction_t GenPIDDriverFunction;
}  ; //


#ifdef __cplusplus
}
#endif

#endif 
